using System;
using System.Collections;
using System.Reflection;
using MAPI;
using Exchange.Export.DataHandler;
using SharePoint.ImportExport.Core;

using ExchangeSiteParameters;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace cmdExchangeExtractor
{
	/// <summary>
	/// Summary description for Class1.
	/// </summary>
	class App
	{
		public App ()
		{
		}
		private static MAPI.Session oSession;
		private static bool loggedOn= false;
		private static ExchangeSiteParameters.SiteParameters siteParameters = new ExchangeSiteParameters.SiteParameters ();
		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]

		static void Main(string[] args)
		{
			if (args.Length<2)
			{
				Console.WriteLine("Exchange Extractor Version {0}", version);
				Console.WriteLine("Incorrect parameters!");
				Console.WriteLine("Usage");
				Console.WriteLine("");
				Console.WriteLine("-exchangeserver [Name of Exchange Server]");
				Console.WriteLine("-account [User account used when logging into Exchange]");
				Console.WriteLine("-exchangestore [Public Folders/Mailbox - username]");
				Console.WriteLine("-out x:\\outputfolder");
				Console.WriteLine("-type [Site]");
				Console.WriteLine("-name sitename");	
				Console.WriteLine("-mailsavetype [MSG-File/RTF-File/TXT-File/HTM-File");	
				Console.WriteLine("-conversation [Discussion/Mail items]");
				Console.WriteLine("");
				Console.WriteLine("Optional");
				Console.WriteLine("-startfromfolder [Startpoint of the extraction]");
				Console.WriteLine("-managedpath [Sites]");
				Console.WriteLine("-owner  [Domain account of user]");
				Console.WriteLine("-date dd.mm.yyyy hh.MM.ss (in local format)");
				Console.WriteLine("-enddate dd.mm.yyyy  hh.MM.ss (in local format)");
				Console.WriteLine("-contact user@domain.com");
				Console.WriteLine("-restrictbysize [Size in bytes]");
				Console.WriteLine("-addwebpart [True/False]");
				Console.WriteLine("-onlythisfolder [True/False]");
				Console.WriteLine("-properties path to properties xml file");
				Console.WriteLine("-configFile path to config xml file");
				Console.WriteLine("-lastSucceededDate dd.mm.yyyy  hh.MM.ss (in local format)");
				return;
			}

			string mailSaveType="MSG";
			string ExchangeServer="";
			string Account="";
			string StartFromFolder="";
			string Root="sites";
			string SiteOrAreaName="";
			string Owner="";
			string Contact="";
			string Conversation="Mail";
			string restrictBySize="";
			string FolderToExtract="";
			string xmlPropertiesFile="properties.xml";
			string ExchangeStore="Public Folders";
			DateTime dateFrom=DateTime.MinValue;
			DateTime dateEnd=DateTime.MinValue;
			bool ExportSecurity= false;
			bool AddWebPart= false;
			bool OnlyThisFolder= false;
			string configFile ="";
			string convertTo = "";
			uint isrecurringtag = 0;
			uint recurrencedatatag = 0;
			string logFile = "exLog.log";

			DateTime lastSucceededDate=DateTime.MinValue;
			SiteType containerType=SiteType.Undefined;
			
			Parameter siteParameter = new Parameter ();

			for(int i = 0;i<args.GetLength(0);i+=2)
			{
				string lowerarg=args[i];
				string data=args[i+1];
				switch(lowerarg.ToLower())
				{
					case "-properties":
						xmlPropertiesFile=data;
						break;

					case "-mailsavetype":
						mailSaveType=data;
						break;
					case "-folder":
						StartFromFolder=data;
						break;
					case "-exchangeserver":
						ExchangeServer=data;
						break;
					case "-account":
						Account=data;
						break;
					case "-type":
						containerType=(SiteType)Enum.Parse(typeof(SiteType),data, false);
						break;
					case "-managedpath":
						Root=data;
						break;
					case "-name":
						SiteOrAreaName=data;
						break;
					case "-owner":
						Owner=data;
						break;
					case "-contact":
						Contact=data;
						break;
					case "-conversation":
						Conversation=data;
						break;
					case "-exchangestore":
						ExchangeStore=data;
						break;
					case "-restrictbysize":
						restrictBySize=data;
						break;
					case "-out":
						FolderToExtract=data;
						break;
					case "-exportsecurity":
						ExportSecurity=bool.Parse(data);
						break;
					case "-addwebpart":
						AddWebPart=bool.Parse(data);
						break;
					case "-onlythisfolder":
						OnlyThisFolder=bool.Parse(data);
						break;
					case "-datethreshold":
						dateFrom=DateTime.Parse(data);
						break;
					case "-lastsucceededdate":
						lastSucceededDate =DateTime.Parse(data);
						break;
					case "-enddate":
						dateEnd=DateTime.Parse(data);
						break;

					case "-configfile":
						configFile = data;
						break;
					
					case "-convertto":
						convertTo = data;
						break;

					case "-isrecurringtag":
						isrecurringtag = uint.Parse(data);
						break;

					case "-recurrencedatatag":
						recurrencedatatag = uint.Parse(data);
						break;
					case "-logFile":
						logFile= data;
						break;

				}
			}
			
            if (configFile.Trim()!="")
			{
				setSiteParamters (configFile);
				siteParameter = siteParameters.List[0];
				
				ExchangeServer=siteParameter.ServerName;
				Account=siteParameter.Alias;
				containerType = (SiteType)Enum.Parse(typeof(SiteType),siteParameter.ContainerType, false);
				Conversation = siteParameter.conversation;
				SiteOrAreaName = siteParameter.SiteName;
				if (siteParameter.LastSucceededDate==null)
					siteParameter.LastSucceededDate="";
				if (siteParameter.LastSucceededDate.Trim() != "")
					lastSucceededDate = DateTime.Parse(siteParameter.LastSucceededDate);
				if (siteParameter.dateTimeThreshHold==null)
					siteParameter.dateTimeThreshHold="";
				if (siteParameter.dateTimeThreshHold.Trim() != "")
					dateFrom = DateTime.Parse(siteParameter.dateTimeThreshHold);
				FolderToExtract = siteParameter.FolderToExtract;
				restrictBySize = siteParameter.RestrictBySize;
				OnlyThisFolder = bool.Parse(siteParameter.onlyTopFolder);
				StartFromFolder = siteParameter.StartFromFolder;
				AddWebPart=bool.Parse(siteParameter.addWebPart);
				ExportSecurity=bool.Parse(siteParameter.exportSecurity);
				mailSaveType = siteParameter.MailSaveType;
				convertTo = siteParameter.ConvertTo;
				logFile = siteParameter.logFile;
				string isRecurringTag = siteParameter.isrecurringtag.ToString();
				if (isRecurringTag.Trim()!="")
					isrecurringtag = System.Convert.ToUInt32(isRecurringTag,16);
				string recurrenceDataTag = siteParameter.recurrencedatatag.ToString();
				if (recurrenceDataTag.Trim()!="")
					recurrencedatatag = System.Convert.ToUInt32(siteParameter.recurrencedatatag.ToString(),16);
			}
			
            if (logFile.Trim() =="")
				logFile = "exOut.log";
			Logger.Init(@logFile,ErrorLevel.Information);
			Logger.LogDataSendingEvent += new Logger.LogDataEventHandler(IncomingEventLogData);
			Logger.Log(ErrorLevel.Progress, "Exchange Public Folder extractor Version "+version+ " starting...");
			
            containerType = SiteType.Site;

			if (SiteType.Undefined==containerType)
			{
				Logger.Log(ErrorLevel.Error, "Please select the container type");
				Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
				return;
			}
			
            if (Conversation.Trim().Length == 0)
			{
				Logger.Log(ErrorLevel.Error,"Please select whether a folder will be exported as a threaded discussion or as a document library");
				Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
				return;
			}

			if (SiteOrAreaName.Trim().Length == 0)
			{
				Logger.Log(ErrorLevel.Error,"A Site/Area name must be specified");
				Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
				return;
			}

            if (FolderToExtract.Trim().Length == 0)
			{
				Logger.Log(ErrorLevel.Error,"An output folder must be specified");
				Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
				return;
			}

            string ProfileInfo = ExchangeServer + "\n" + Account;
            if (ProfileInfo.Length == 1)
                ProfileInfo = "";
            if (!Logon(ProfileInfo))
            {
                Logger.Log(ErrorLevel.Error, "Could not logon");
                Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
                return;
            }

			ArrayList extensions = new ArrayList();
			ArrayList folders = new ArrayList();

            if (!File.Exists(xmlPropertiesFile))
            {
                FileInfo di = new FileInfo( Assembly.GetExecutingAssembly().Location);
                xmlPropertiesFile = di.DirectoryName + "\\" + xmlPropertiesFile;
                if (!File.Exists(xmlPropertiesFile))
                {
                    Logger.Log(ErrorLevel.Error, "The properties file did not exist");
                    Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
                    return;
                    
                }

            }
			
			if (configFile.Trim()=="")
			{
				siteParameter = new Parameter ();
				siteParameter.ContainerType = containerType.ToString();
				siteParameter.ManagedPath =  Root;
				siteParameter.SiteName =  SiteOrAreaName;
				siteParameter.Owner = Owner;
				siteParameter.Contact=Contact;
				siteParameter.conversation = Conversation;
				siteParameter.store = ExchangeStore;
				siteParameter.exportSecurity = ExportSecurity.ToString();
				siteParameter.addWebPart= AddWebPart.ToString();
				siteParameter.dateTimeEnd = dateEnd.ToString();
				siteParameter.XMLProps = xmlPropertiesFile;
                siteParameter.FolderToExtract = FolderToExtract;
                siteParameter.dateTimeThreshHold=dateFrom.ToString();
				siteParameter.ConvertTo = convertTo;
				siteParameter.isrecurringtag = isrecurringtag.ToString();
				siteParameter.recurrencedatatag = recurrencedatatag.ToString();
				isrecurringtag = System.Convert.ToUInt32(siteParameter.isrecurringtag.ToString(),16);
				recurrencedatatag = System.Convert.ToUInt32(siteParameter.recurrencedatatag.ToString(),16);
			}
			else
				Logger.Log(ErrorLevel.Progress,"Config file in use is: "+configFile);
			/*if (isrecurringtag = 0 || recurrencedatatag = 0)
			{
				Logger.Log(ErrorLevel.Error,"Please specify the tags for recurrence info in the configuration file");
				Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
				return;
			}
			*/
			Exporter exportWrapper=new Exporter(mailSaveType,StartFromFolder);
			exportWrapper.oSession=oSession;

			helperFunctions oHelper = new helperFunctions(); 

			string path = oHelper.createFolder(FolderToExtract);

			Logger.Log(ErrorLevel.Information,"Created folder "+FolderToExtract);
			if (siteParameter.Interval==null)
				siteParameter.Interval="";


			exportWrapper.getMessages(folders,extensions,restrictBySize,dateFrom, path, OnlyThisFolder, lastSucceededDate.ToString(),ref siteParameter);
			
			try
			{
				string filename=FolderToExtract+ "\\OutPutconfig.xml";
				siteParameters.Serialize(filename);
			}
			catch
			{
			}

			try
			{
				oSession.Logoff();
				loggedOn= false;
			}
			catch (Exception LogoffEx)
			{
				Logger.Log(ErrorLevel.Error,"Error logging off: "+LogoffEx.Message);
			}

			Logger.Log(ErrorLevel.Progress,"All Done!");
			Logger.LogDataSendingEvent -= new Logger.LogDataEventHandler(IncomingEventLogData);
			return;


			
		}
		
		static string version = "Version 1.0";
		public void ServiceInterface(string[] args)
		{
			Main(args);
			
		}
		private static void IncomingEventLogData(object sender, SPEventArgs e)
		{
			string logArgs = DateTime.Now.ToLongTimeString()+ ":  " + e.Message;
			Console.WriteLine("{0}\t\t{1}",logArgs.Substring(0,logArgs.IndexOf("-")),logArgs.Substring(logArgs.IndexOf("-")+1));
		}

		private static bool Logon(string sProfileInfo)
		{
			if (loggedOn) //Already logged on
				return true;
			bool bRetValue= false;
			object vEmpty = Missing.Value;
			try
			{
				if (null==oSession)
					oSession=new MAPI.Session();
				if (sProfileInfo.Trim().Length>1)
					oSession.Logon(vEmpty, vEmpty, true, true, 0, true, sProfileInfo);
				else
					oSession.Logon(vEmpty, vEmpty, true, true, 0, true, vEmpty);
				loggedOn=true;
				bRetValue=true;
				Logger.Log(ErrorLevel.Information,"Logged on to mailbox "+sProfileInfo.Replace("\n","-"));

				//Kimmo changed
			}
			catch (System.Runtime.InteropServices.COMException Ex)
			{
				Logger.Log(ErrorLevel.Error,"Could not logon to mailbox "+sProfileInfo.Replace("\n","-")+ ". Error: "+Ex.Message);
				loggedOn= false;
			}
			return bRetValue;
		}
		private static bool setSiteParamters (string fileName)
		{
			try
			{
				FileStream fs = new FileStream(fileName , FileMode.Open);
				XmlReader reader = new XmlTextReader(fs);
				XmlSerializer serializer = new  XmlSerializer(typeof(ExchangeSiteParameters.SiteParameters));
				
				siteParameters = (ExchangeSiteParameters.SiteParameters) serializer.Deserialize(reader);
				fs.Close();
				return (true);
			}
			catch (Exception ex)
			{
				Logger.Log(ErrorLevel.Error,"Could not find siteParametrs file "+fileName+ ". Error: "+ex.Message);
				return (false);
			}

		}


	}
}
